#pragma once

#include <common_definition.h>
#include <project_config.h>
#include <stm32f4xx_hal.h>

namespace hal
{
    class systick {
    public:
        // 获取1/4MHz秒
        ALWAYS_INLINE static uint32_t get_tick()
        {
            return HAL_GetTick();
        }

        // 获取微秒时间间隔
        static uint32_t calc_interval(const uint32_t prev_tick, const uint32_t last_tick)
        {
            return (last_tick - prev_tick) >> 2;
        }
    };

    class delay {
        ALWAYS_INLINE static auto get_ns_tick()
        {
            return TIM7->CNT;
        }

    public:
        static void us(const uint16_t us_) noexcept
        {
            const uint16_t delay_ticks = us_ << 2; // 计算所需计数（4MHz→1µs=4ticks）
            const uint16_t start = get_ns_tick(); // 直接读取16位计数器

            // 通过无符号数差值自动处理溢出
            while (static_cast<uint16_t>((get_ns_tick() - start)) < delay_ticks) {
            }
        }

        static void ms(const uint32_t ms_) noexcept
        {
            const uint32_t target = systick::get_tick()+ms_;
            while (systick::get_tick()>target){}
            while (systick::get_tick()<target) {
                // __WFI(); // 进入休眠模式，等待中断唤醒
            }
        }
    };

    /**
 * @brief 异步延迟类(utils里的协程库更好用)
 * @tparam get_tick 获取当前时间函数，基本单位一般为1ms
 * @note 目前思路是，先用这三个32位变量，delay_tick这个是可以换成函数形参的
 *
 */
    class asyncDelay {
    public:
        asyncDelay() : start_tick(0), final_tick(0), delay_tick(100)
        {
        }

        explicit asyncDelay(uint32_t delay_tick) : start_tick(0), final_tick(0), delay_tick(delay_tick)
        {
        }

        void reset()
        {
            start_tick = HAL_GetTick();
            final_tick = start_tick + delay_tick;
        }

        bool is_timeout()
        {
            // 非阻塞延迟
            if (final_tick < start_tick) {
                // 检测溢出情况
                if (HAL_GetTick() > final_tick && HAL_GetTick() < start_tick) {
                    // 重置
                    start_tick = HAL_GetTick();
                    final_tick = start_tick + delay_tick;
                    // 标志记为1
                    return true;
                }
            } else {
                if (HAL_GetTick() > final_tick) {
                    // 重置
                    start_tick = HAL_GetTick();
                    final_tick = start_tick + delay_tick;
                    // 标志记为1
                    return true;
                }
            }
            return false;
        }

        void set_delay_tick(const uint32_t tick)
        {
            delay_tick = tick;
        }

    private:
        uint32_t start_tick;
        uint32_t final_tick;
        uint32_t delay_tick; // 默认100个tick
    };
}
